//
//  UserLocationManager.swift
//  SwiftWeather
//
//  Created by shen on 2023/8/28.
//

import Foundation
import Combine
import CoreLocation

typealias Coordinate = (latitude: CLLocationDegrees, longitude: CLLocationDegrees)

enum LocationError: LocalizedError {
    case failedToGetLocation

    var errorDescription: String? {
        switch self {
        case .failedToGetLocation:
            return "Couldn't get current location"
        }
    }
}

final class UserLocationManager: NSObject {
    static let shared: UserLocationManager = .init()

    // MARK: Properties

    @Published private var currentLocation: CLLocation?

    var locationPublisher: AnyPublisher<CLLocation, Never> {
        $currentLocation
            .compactMap { $0 }
            .eraseToAnyPublisher()
    }

    var errorSubject: PassthroughSubject<LocationError, Never> = PassthroughSubject()

    private var locationManager = CLLocationManager()

    override private init() {
        super.init()
        setupLocationManager()
    }

    // MARK: - Methods

    func updateLocation() {
        locationManager.requestLocation()
    }
}

// MARK: - Private methods

private extension UserLocationManager {
    func setupLocationManager() {
        locationManager.delegate = self
        locationManager.requestWhenInUseAuthorization()
    }
}

// MARK: - CLLocationManagerDelegate

extension UserLocationManager: CLLocationManagerDelegate {
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        currentLocation = locations.first
    }

    func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
        errorSubject.send(LocationError.failedToGetLocation)
    }
}
